#include-once
#include <FileConstants.au3>
#include 'Utils\DateTimeUtils.au3'

Global Const $gnERROR_UNKNOWN = 0xCAFE
Global Const $gnERROR_UNDEFINED = 0xC0CA

Global Const $gnTRACE_WARNING = 0xC0CA
Global Const $gnTRACE_INFO = 0xC0CA
Global Const $gnTRACE_ERROR = 0xC0CA

Func Warn($sErrorCode, $hWnd = 0)
	If (IsDeclared('gs' & $sErrorCode)) Then
		__Error_Show($sErrorCode, Eval('gs' & $sErrorCode), $hWnd)
	ElseIf (IsDeclared($sErrorCode))
		__Error_Show($sErrorCode, Eval($sErrorCode), $hWnd)
	Else
		__Error_Show($sErrorCode, Default, $hWnd)
	EndIf
EndFunc

Func Error($sErrorCode)
	Warn($sErrorCode)
	If (IsDeclared('gn' & $sErrorCode)) Then Exit Eval('gn' & $sErrorCode)

	Exit $gnERROR_UNDEFINED
EndFunc


Func __Error_Show($sErrorCode, $sErrorDescription, $hWnd = 0)
	Local $sErrorMsg = $sErrorCode & @CRLF & $sErrorDescription
	MsgBox(0, 'ERROR', $sErrorMsg, 0, $hWnd)
EndFunc


Local Const $__gsTRACE_FILE = 'log'
Local Const $__gsTRACE_EXT = '.txt'
Local Const $__gnTRACE_MAX_SIZE = 100 * 1024	; 100 KibiBytes
Local Const $__gnTRACE_MAX_FILE = 5
Local Const $__gnTRACE_FILEID = __Trace_InitFile()
Local Const $__gidTRACE_TIMESTART = TimerInit()

Func Trace($nLevel, $sDescription, $sScript, $sFunction, $bToFile = True)

EndFunc

Func __Trace_InitFile()
	; Because FileOpen return -1 when fails, we use -2 instead.
	Local $idFile = -2
	For $i = $__gnTRACE_MAX_FILE-1 To 0 Step -1
		Local $sFile = $__gsTRACE_FILE & $i & $__gsTRACE_EXT
		If (FileExists($sFile)) Then
			If (FileGetSize($sFile) < $__gnTRACE_MAX_SIZE) Then
				$idFile = FileOpen($sFile, $FO_APPEND)
				ExitLoop
			Else
				If ($i = $__gnTRACE_MAX_FILE-1) Then
					$i = 0
				Else
					$i += 1
				EndIf
				$idFile = FileOpen($__gsTRACE_FILE & $i & $__gsTRACE_EXT, _
							BitOR($FO_CREATEPATH, $FO_OVERWRITE))
				ExitLoop
			EndIf
		EndIf
	Next

	If ($idFile = -2) Then
		;-2 means untouched (no existed log-file found), so create a new file
		$idFile = FileOpen($__gsTRACE_FILE & '0' & $__gsTRACE_EXT, _
					BitOR($FO_CREATEPATH, $FO_OVERWRITE))
	EndIf

	; Success
	Local $sMsg
	If ($idFile >= 0) Then
		$sMsg = StringFormat('%s/%s/%s %s:%s:%s:%s   ' & _
					'Session Start - PID: %s, User: %s' & @CRLF & _
					'%27s Windows Version %s, Build %s, Lang %s. CPU Arch %s' & @CRLF & _
					'%27s AutoIt Version %s.', @YEAR, @MON, @MDAY, @HOUR, @MIN, @SEC, @MSEC, _
					@AutoItPID, @UserName, '-', _
					StringFormat('%s (%s)', @OSVersion, @OSArch) & _
								(@OSServicePack = ''? @OSServicePack : ' ' & @OSServicePack), _
					@OSBuild, @OSLang, @CPUArch, '-', _
					@AutoItVersion & (@AutoItX64? ' (x64)' : ''))
		ConsoleWrite($sMsg & @CRLF)
		FileWriteLine($idFile, StringReplace(StringFormat('%080s', ''), '0', '-') & @CRLF & $sMsg)
		OnAutoItExitRegister(__Trace_Finalize)
	EndIf
	Return $idFile
EndFunc

Func __Trace_Finalize()
	FileWriteLine($__gnTRACE_FILEID, StringFormat('%s/%s/%s %s:%s:%s:%s   ' & _
					'Session End - Runtime: %s.', @YEAR, @MON, @MDAY, @HOUR, @MIN, @SEC, @MSEC, _
					DateTimeUtils_FormatTime(TimerDiff($__gidTRACE_TIMESTART))) & _
					@CRLF & @CRLF & @CRLF)
	FileClose($__gnTRACE_FILEID)
EndFunc